package core.proto.rightwindow;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Hashtable;
import java.util.Properties;

import org.apache.commons.io.FilenameUtils;

import com.oreilly.servlet.HttpMessage;

import core.proto.AllComponents;
import core.proto.InfoViz;
import core.proto.Util;
import core.proto.annotation.Annotation;
import core.proto.annotation.AnnotationUI;

/**
 * Class with methods to communicate updates between annotation and its associate post it. 
 * 
 * Also, takes care of broadcasting PostIt updates to the server.  
 */
public class LeftRightCommunicator {

	private LeftRightCommunicator() {}

	static Hashtable<AnnotationUI, PostIt> anno2Post;
	static Hashtable<PostIt, AnnotationUI> post2Anno;

	static {
		anno2Post = new Hashtable<AnnotationUI, PostIt>();
		post2Anno = new Hashtable<PostIt, AnnotationUI>();
	}

	private static void addPostItForAnnotation (AnnotationUI ui) {
		if (! anno2Post.containsKey(ui)) {
			// Create post it
			PostIt postIt = new PostIt(InfoViz.userToken, true);
			// Add to board pane
			BoardPane.getInstance().addPostItFromLeftWindow(postIt);
			// Associate the annotation with the post it.
			anno2Post.put(ui, postIt);
			post2Anno.put(postIt, ui);
		}
	}

	/**
	 * Call when annotation is updated. 
	 * Updates existing corresponding post it. 
	 * Pushes the updates up to the server.  
	 * @param ui
	 */
	public static void annotationUpdated (AnnotationUI ui) {
		addPostItForAnnotation (ui);

		PostIt postIt = anno2Post.get(ui);
		// look up post it and update its text
		anno2Post.get(ui).setText(ui.getUserText());
		if (Annotation.shouldDeleteAnnotationWith(ui.getUserText())){
			// Tell whiteboard to remove it. 
			BoardPane.getInstance().removePostIt(anno2Post.get(ui));

			// Update hash tables.
			post2Anno.remove(anno2Post.get(ui));
			anno2Post.remove(ui);
		}
		// regardless of whehter we removed PostIt, we send an update 
		// to the other client, which we assume will update accordingly
		// (it has to because it's running the same codebase as us and we 
		// have coded that in). 
		pushPostItUpdates2Server (postIt);
	}

	/**
	 * Analogous to the annotation update but pushes updates back to the annotations. 
	 * @param postIt
	 */
	public static void postItUpdated (PostIt postIt) {
		pushPostItUpdates2Server (postIt);
		if (post2Anno.containsKey(postIt)){
			// Update associated annotation.  
			boolean deleted = post2Anno.get(postIt).externalSetText (postIt.getText());
			// update hash table from deletions. 
			if (deleted) {
				anno2Post.remove(post2Anno.get(postIt));
				post2Anno.remove(postIt);
				BoardPane.getInstance().removePostIt(postIt);
			}
		} else {
			// Check if we should delete the post it anyhow. 
			if (Annotation.shouldDeleteAnnotationWith(postIt.getText())){
				BoardPane.getInstance().removePostIt(postIt);
			}
		}
	}

	private static void pushPostItUpdates2Server (final PostIt postIt) {
		final String networkString;
		try {
			networkString = postIt.toNetworkString();
		} catch (IOException e1) {
			return;
		}
		new Thread(){
			public void run() {
				try {
					Util.p("Debug : pushing postit out,content="+postIt.toNetworkString());
					WebUtil.sendPostIt(networkString);
				} catch (IOException e) {
					System.err.println("Error sending out postIt update.");
				}		
			}
		}.start();
	}
}
